﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using System.Timers;
using System.Drawing.Drawing2D; // For CompositingQuality
using DrawTools;// For DrawArea

namespace RobotCleaner
{
    public partial class RobotCleanerV2 : Form
    {
        public RobotCleanerV2()
        {
            InitializeComponent();
            Control.CheckForIllegalCrossThreadCalls = false;

            SetStyle(ControlStyles.UserPaint, true);
            SetStyle(ControlStyles.AllPaintingInWmPaint, true);   //   禁止擦除背景.
            SetStyle(ControlStyles.DoubleBuffer, true);   //   双缓冲
            //------------------------------------------------------
            this.SetStyle(ControlStyles.OptimizedDoubleBuffer |
                ControlStyles.AllPaintingInWmPaint | 
                ControlStyles.UserPaint, true);
            this.UpdateStyles();
            //以上两句是为了设置控件样式为双缓冲，这可以有效减少图片闪烁的问题，
            //关于这个大家可以自己去搜索下
            // From ：http://www.cnblogs.com/stg609/archive/2008/03/19/1113694.html
            // Sep 30,2013 09:37
            //-------------------------------------------------------
        }
        #region 全局变量
        /// <summary>
        /// 画图区域
        /// </summary>
        //private DrawArea drawArea;
        /// <summary>
        /// 机器人
        /// </summary>
        Robot r = new Robot();
        /// <summary>
        /// 充电器类
        /// </summary>
        Charger c = new Charger();
        /// <summary>
        /// 机器人行走地图
        /// </summary>
        Map map = new Map();
        /// <summary>
        /// 机器人行走算法
        /// </summary>
        CleanAlgorithm cleanAlgo = new CleanAlgorithm();
        /// <summary>
        /// Debug类
        /// </summary>
        CleanDebug cleanDebug = new CleanDebug();
        /// <summary>
        /// Timer
        /// </summary>
        System.Timers.Timer t;
        #endregion
        #region 事件函数
        //private Color color;
        //private Color bcolor;
        /// <summary>
        /// 初始化DrawArea
        /// </summary>
        private void initDrawTool()
        {
            // Create draw area
            //drawArea = new DrawArea();

            //drawArea.Scolor = color;
            //drawArea.Location = new System.Drawing.Point(0, 0);
            //drawArea.Size = new System.Drawing.Size(10, 10);
            //drawArea.Owner = this.panel1;
            //this.Controls.Add(drawArea);

            // Helper objects (DocManager and others)
            //InitializeHelperObjects();

            //drawArea.Initialize(this, docManager);
            //ResizeDrawArea();

            //LoadSettingsFromRegistry();

            // Submit to Idle event to set controls state at idle time
            //Application.Idle += delegate(object o, EventArgs a)
            //{
            //    SetStateOfControls();
            //};

            // Open file passed in the command line
            //if (ArgumentFile.Length > 0)
            //    OpenDocument(ArgumentFile);

            // Subscribe to DropDownOpened event for each popup menu
            // (see details in MainForm_DropDownOpened)
            //foreach (ToolStripItem item in menuStrip1.Items)
            //{
            //    if (item.GetType() == typeof(ToolStripMenuItem))
            //    {
            //        ((ToolStripMenuItem)item).DropDownOpened += MainForm_DropDownOpened;
            //    }
            //}
        }
        /// <summary>
        /// 窗体加载执行函数
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void RobotCleanerV2_Load(object sender, EventArgs e)
        {
            try
            {
                // 初始化清扫类对象 Sep 29,2013 15:44 EndlessRain
                r.initAnalyze();
                // 实例化 DrawArea Sep 28,2013 11:02
                initDrawTool();
                // Sep 23,2013 09:26 for timer 
                t = new System.Timers.Timer(r.R_Time);//实例化Timer类，设置间隔时间为robot时间
                t.Elapsed += new System.Timers.ElapsedEventHandler(Cleaning);//到达时间的时候执行事件；

                // for initial trackBarSpeed value
                this.trackBarSpeed.Value = 1000 - r.R_Time;

                // 选择第三个选项卡为默认
                this.tabControl1.SelectedIndex = 2;

                // For test
                //this.tabControl1.SelectedIndex = 1;

                // 获取时间间隔
                timerSimulation.Interval = r.R_Time;

                // 初始化机器人行走地图
                map.Map_Init(this.panelSimulation);

                // 初始化可清理区域坐标
                map.Map_AddWallPoint(new Point(r.get_R_X(), r.get_R_Y()));

                // 画初始机器人位置
                //using (Graphics g = new Graphics())
                //{
                //    g.drawEllipse(r, panel);
                //}

                // For ObstaclePoint
                // Add Points
                //map.ObstaclePoint.Add(new Obstacle(new Point(300, 300), new Point(400, 400)));
                //map.ObstaclePoint.Add(new Obstacle(new Point(90, 130), new Point(300, 400)));
                //map.ObstaclePoint.Add(new Obstacle(new Point(200, 400), new Point(500, 500)));
            }
            catch (Exception ex)
            {
                MessageBox.Show("初始化出错：" + ex.ToString());
            }
           
        }
        /// <summary>
        /// 点击开始清扫按钮
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Clean_Click(object sender, EventArgs e)
        {
            //// 开始清扫
            //timerSimulation.Enabled = true;

            // 注： 以下注释行放到全局变量
            //System.Timers.Timer t = new System.Timers.Timer(10);//实例化Timer类，设置间隔时间为10000毫秒；
            t.AutoReset = true;//设置是执行一次（false）还是一直执行(true)；
            t.Enabled = true;//是否执行System.Timers.Timer.Elapsed事件；

            // 开启线程
            //string strInfo = string.Empty;                             //定义一个字符串，用来记录线程相关信息
            //Thread myThread = new Thread(new ThreadStart(Cleaning));  //实例化Thread线程类对象
            //myThread.Start();                                          //启动主线程
            ////获取线程相关信息
            //strInfo = "线程唯一标识符：" + myThread.ManagedThreadId;
            //strInfo += "\n线程名称：" + myThread.Name;
            //strInfo += "\n线程状态：" + myThread.ThreadState.ToString();
            //strInfo += "\n线程优先级：" + myThread.Priority.ToString();
            //strInfo += "\n是否为后台线程：" + myThread.IsBackground;
            //while (true)
            //{
            //Thread.Sleep(100);
            //}                           //使主线程休眠1秒钟
            //myThread.Abort("退出");                                    //通过主线程阻止新开线程
            //myThread.Join();                                           //等待新开的线程结束
            //MessageBox.Show("线程运行结束");
            //richTextBox1.Text = strInfo;
        }
        /// <summary>
        /// 点击暂停清扫按钮
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Pause_Click(object sender, EventArgs e)
        {
            // 暂停清扫
            //timerSimulation.Enabled = false;

            // 暂停清扫 for timer Sep 23,2013 09:52
            t.Enabled = false;
        }
        /// <summary>
        /// timer
        /// </summary>
        /// <param name="sender"></param>        /// <param name="e"></param>
        private void timerSimulation_Tick(object sender, EventArgs e)
        {
            // 清扫
            //this.Cleaning(sender,e);
            // 输出信息
            r.Analyze.Output(this.richTxbNodeInfo);
        }
        /// <summary>
        /// 点击退出
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void 退出ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            // 退出
            Application.Exit();
        }
        /// <summary>
        /// 点击关于
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void 关于ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            // 关于
            MessageBox.Show("东莞市明珍电器有限公司", "关于");
        }
        #endregion
        #region 机器人初始化
        private void initRobot(Map map, Robot r, Panel panel)
        {

        }
        #endregion

        /// <summary>
        /// 新建机器人
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void RobotCreate_Click(object sender, EventArgs e)
        {
            this.RobotDiameter.ReadOnly = false;
            this.RobotWheelDiameter.ReadOnly = false;
            this.RobotBrushDiameter.ReadOnly = false;
        }

        /// <summary>
        /// 检测是否是数字
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void RobotDiameter_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (!(Char.IsNumber(e.KeyChar)) && e.KeyChar != (char)13 && e.KeyChar != (char)8)
            {
                e.Handled = true;
            }
        }

        private void RobotDiameter_Leave(object sender, EventArgs e)
        {
            try
            {
                r.R_Height = Convert.ToInt32(this.RobotDiameter.Text);
                r.R_Width = Convert.ToInt32(this.RobotDiameter.Text);
                r.drawRobot(r, panel2);
            }
            catch (Exception ex)
            {
                this.lblMessage.Text = "消息：" + ex.Message;
                this.lblMessage.Visible = true;
            }
        }

        private void RobotDiameter_TextChanged(object sender, EventArgs e)
        {
            this.panel2.Invalidate();
        }

        //Bitmap buffer = null;
        private void panelSimulation_Paint(object sender, PaintEventArgs e)
        {
            // 初始化机器人行走地图
            map.Map_Init(this.panelSimulation);

            //Bitmap bmp = new Bitmap(panelSimulation.Width, panelSimulation.Height);
            //Rectangle rec = new Rectangle(0,0,panelSimulation.Width, panelSimulation.Height);
            //panelSimulation.DrawToBitmap(bmp,rec);
            //bmp.Save(@"E:\b.bmp");

            //=======================================================
            //if (buffer == null) buffer = new Bitmap(panel1.Width, panel1.Height);
            //if (buffer.Width != panel1.Width || buffer.Height != panel1.Height) buffer = new Bitmap(panel1.Width, panel1.Height);
            //using (Graphics g = Graphics.FromImage(buffer))
            //{
            //    g.DrawLine(Pens.Blue, 0, 0, 175, 233);
            //}
            //e.Graphics.DrawImage(buffer, 0, 0);
            //buffer.Save(@"E:\buffer.bmp");

            //=====================================================
            //Bitmap bit = new Bitmap(panelSimulation.Width, panelSimulation.Height);//实例化一个和窗体一样大的bitmap 
            //Graphics g=Graphics.FromImage(bit); 
            //g.CompositingQuality = CompositingQuality.HighQuality;//质量设为最高 
            //g.CopyFromScreen(panelSimulation.Left, panelSimulation.Top, 0, 0, new Size(panelSimulation.Width, panelSimulation.Height));//保存panelSimulation区域为图片 
            ////g.CopyFromScreen(panelSimulation.PointToScreen(Point.Empty), Point.Empty, panelSimulation.Size);//只保存某个控件（这里是panelSimulation）
            //bit.Save(@"E:\123.png");//默认保存格式为PNG，保存成jpg格式质量不是很好
        }

        // 加载地图 Sep22,2013 10:05
        private void btnLoadMap_Click(object sender, EventArgs e)
        {
            if (map.ObstaclePoint.Count <= 20)
            {
                //map.ObstaclePoint.Add(new Obstacle(new Point(0, 400), new Point(150, 500)));
                //map.ObstaclePoint.Add(new Obstacle(new Point(90, 110), new Point(200, 300)));
                ////map.ObstaclePoint.Add(new Obstacle(new Point(200, 200), new Point(300, 400)));
                ////map.ObstaclePoint.Add(new Obstacle(new Point(400, 400), new Point(480, 500)));
                //map.ObstaclePoint.Add(new Obstacle(new Point(400, 110), new Point(480, 500)));

                //while (map.ObstaclePoint.Count <= 3)
                //{
                ////=====================================================
                //map.DirtyPoint.Add(new DirtyArea(new Point(300, 300), new Point(400, 400)));
                map.ObstaclePoint.Add(new Obstacle(this.generatePoint(),
                    new Point(this.generatePoint().X + this.generatePoint().X / 3,
                              this.generatePoint().Y + this.generatePoint().Y / 2)));
                //this.panelSimulation.Invalidate();
                //for (int i = 0; i < map.ObstaclePoint.Count; i++)
                //{
                //    map.ObstaclePoint[i].drawObstacle(
                //        new Point(map.ObstaclePoint[i].O_X, map.ObstaclePoint[i].O_Y),
                //        new Size(map.ObstaclePoint[i].O_width, map.ObstaclePoint[i].O_height),
                //        panelSimulation);
                //}
                ////==========================================================
                //}
                // 加载成功
                //MessageBox.Show("加载地图成功!");
            }
            else
            {
                MessageBox.Show("加载地图完成!");
            }
        }
        /// <summary>
        /// 重新清扫
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ReClean_Click(object sender, EventArgs e)
        {
            this.panelSimulation.Invalidate();
            this.r.init_XY();
        }

        /// <summary>
        /// 清扫
        /// </summary>
        private void Cleaning(Object sender,ElapsedEventArgs e)
        {
            try
            {
                //// 初始化机器人行走地图
                map.Map_Init(this.panelSimulation);
                /// 机器人运行模式 0-沿墙   1-左拐N°2-右拐N°
                ///                         3-S型    4-倒退
                ///                         5-沿边   6-螺旋
                ///                         7-左右交替
                ///                         -1  随机
                switch (r.R_RUN_MODE)
                {
                    case 0:
                        // 沿墙清扫 (完成待完善)
                        cleanAlgo.robotCleanWall(map, r, panelSimulation);
                        break;
                    case 1:
                        // 左拐清扫 (完成待完善)
                        cleanAlgo.robotCleanTurnLeft(map, r, panelSimulation);
                        break;
                    case 2:
                        // 右拐清扫 (完成待完善)
                        cleanAlgo.robotCleanTurnRight(map, r, panelSimulation);
                        break;
                    case 3:
                        // S 型清扫 （也叫Z型） (完成待完善)
                        cleanAlgo.robotCleanS(map, r, c, panelSimulation);
                        break;
                    case 4:
                        // 倒退清扫 (待完成)
                        cleanAlgo.robotCleanBackwards(map, r, panelSimulation);
                        break;
                    case 5:
                        // 沿边清扫 (待完成)
                        cleanAlgo.robotCleanRound(map, r, panelSimulation);
                        break;
                    case 6:
                        // 螺旋清扫 (完成待完善)
                        cleanAlgo.robotCleanSpiral(map, r, panelSimulation);
                        break;
                    case 7:
                        // 左右交替 (待完成)
                        cleanAlgo.robotCleanLeftRight(map, r, panelSimulation);
                        break;
                    case 8:
                        // 回型清扫 (完成待修改)
                        cleanAlgo.robotCleanClockwise(map, r, panelSimulation);
                        break;
                    case -1:
                        // 随机清扫 (完成 完善中)
                        cleanAlgo.robotCleanStochastic(map, r, panelSimulation);
                        break;
                    default:
                        // Nothing to do here
                        break;
                }
                // 输出调试参数
                cleanDebug.outputDebug(this.richTxbRobotInfo, r);
                cleanDebug.outputDebug03(this.richTxbNodeInfo, r);
            }
            catch (Exception ex)
            {
                MessageBox.Show("执行清扫出错！原因："+ex.Message);
            }
            
        }

        private void button11_Click(object sender, EventArgs e)
        {

        }
        /// <summary>
        /// 移动滑块调节速度
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void trackBarSpeed_Scroll(object sender, EventArgs e)
        {
            t.Interval = 1000 - this.trackBarSpeed.Value;
            this.richTxbNodeInfo.Text= this.trackBarSpeed.Value.ToString();
        }

        /// <summary>
        /// Toolbar buttons handler
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void toolBar1_ButtonClick(object sender, ToolBarButtonClickEventArgs e)
        {
            if (e.Button == tbRectangle)
                CommandRectangle();
            else if (e.Button == tbEllipse)
                CommandEllipse();
            else if (e.Button == tbAbout)
                CommandAbout();
        }
        /// <summary>
        /// Set Rectangle draw tool
        /// </summary>
        private void CommandRectangle()
        {
            MessageBox.Show("矩形");
            //drawArea.ActiveTool = DrawArea.DrawToolType.Rectangle;
        }
        /// <summary>
        /// Set Ellipse draw tool
        /// </summary>
        private void CommandEllipse()
        {
            MessageBox.Show("圆形");
            //drawArea.ActiveTool = DrawArea.DrawToolType.Ellipse;
        }
        /// <summary>
        /// About
        /// </summary>
        private void CommandAbout()
        {
            MessageBox.Show("画图工具 V1.0");
        }

        private void RobotCleanerV2_FormClosed(object sender, FormClosedEventArgs e)
        {
            // 退出
            Application.Exit();
        }
        /// <summary>
        /// 生成随机数
        /// </summary>
        /// <returns></returns>
        private Point generatePoint()
        {
            Point p = new Point();
            Random gen = new Random();
            p.X = gen.Next(90, 300);
            p.Y = gen.Next(100, 500);
            //MessageBox.Show(ran.ToString());
            return p;
        }
        #region 事件处理函数
        /// <summary>
        /// 保存仿真结果
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnSaveResult_Click(object sender, EventArgs e)
        {
            MessageBox.Show("保存仿真结果");
        }
        /// <summary>
        /// 退出仿真界面
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnExit_Click(object sender, EventArgs e)
        {
            MessageBox.Show("退出仿真界面Test Oct 3");
        }
        /// <summary>
        /// 进入仿真界面
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ToEnter_Click(object sender, EventArgs e)
        {
            this.btnExit.Enabled = true;
            this.btnSaveResult.Enabled = true;
        }
        #endregion

        /// <summary>
        /// 手动增加度数，For Test
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnAddDegree_Click(object sender, EventArgs e)
        {
            r.Angle += 15;
        }

        /// <summary>
        /// 手动减少度数，For Test
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnReduceDegree_Click(object sender, EventArgs e)
        {
            r.Angle -= 15;
        }

        private void RobotCleanerV2_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyValue != (char)37 && e.KeyValue != (char)39) 
            { 
                e.Handled = true; 
            }
        }
    }
}